package com.inifitness.admin.core.filter;

import java.io.IOException;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import com.inifitness.common.constants.SecurityConstants;
import com.inifitness.common.result.ResultCode;
import com.inifitness.common.tools.ResponseUtils;

import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.text.CharSequenceUtil;
import lombok.extern.log4j.Log4j2;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * 验证码校验过滤器
 *
 * @author sunjinfeng
 * @version 1.0.0
 * @since 2024/04/18 11:00:00
 */
@Log4j2
public class CaptchaValidationFilter extends OncePerRequestFilter {

  private static final AntPathRequestMatcher LOGIN_PATH_REQUEST_MATCHER = new AntPathRequestMatcher(
      SecurityConstants.LOGIN_PATH, "POST");

  public static final String CAPTCHA_CODE_PARAM_NAME = "captchaCode";
  public static final String CAPTCHA_KEY_PARAM_NAME = "captchaKey";

  private final RedisTemplate<String, Object> redisTemplate;

  private final CodeGenerator codeGenerator;

  public CaptchaValidationFilter(RedisTemplate<String, Object> redisTemplate,
      CodeGenerator codeGenerator) {
    this.redisTemplate = redisTemplate;
    this.codeGenerator = codeGenerator;
  }


  @Override
  public void doFilterInternal(@NotNull HttpServletRequest request,
      @NotNull HttpServletResponse response, @NotNull FilterChain chain)
      throws ServletException, IOException {
    // 检验登录接口的验证码
    if (LOGIN_PATH_REQUEST_MATCHER.matches(request)) {
      // 请求中的验证码
      String captchaCode = request.getParameter(CAPTCHA_CODE_PARAM_NAME);
      // TODO 兼容没有验证码的版本(线上请移除这个判断)
      if (CharSequenceUtil.isBlank(captchaCode)) {
        chain.doFilter(request, response);
        return;
      }
      // 缓存中的验证码
      String verifyCodeKey = request.getParameter(CAPTCHA_KEY_PARAM_NAME);
      String cacheVerifyCode = (String) redisTemplate.opsForValue()
          .get(SecurityConstants.CAPTCHA_CODE_PREFIX + verifyCodeKey);
      if (cacheVerifyCode == null) {
        ResponseUtils.writeErrMsg(response, ResultCode.VERIFY_CODE_TIMEOUT);
      } else {
        // 验证码比对
        if (codeGenerator.verify(cacheVerifyCode, captchaCode)) {
          chain.doFilter(request, response);
        } else {
          ResponseUtils.writeErrMsg(response, ResultCode.VERIFY_CODE_ERROR);
        }
      }
    } else {
      // 非登录接口放行
      chain.doFilter(request, response);
    }
  }

}

